////////////////////////////////////////////////////////////////////////////////
//这里实现标签页的切换
////////////////////////////////////////////////////////////////////////////////


function initSwitchTab() {
    //1.先获取到相关的元素(标签页按钮 , 会话列表 , 好友列表)
    let tabSession  = document.querySelector('.tab .tab-session');
    let tabFriend = document.querySelector('.tab .tab-friend'); 
    //querySelectorAll 可以同时获取到多个元素,得到的结果是个数组
    //[0] 代表的就是会话列表
    //[1] 代表的是好友列表
    let lists = document.querySelectorAll('.list');

    //2.针对标签页按钮, 注册点击事件
      
    //  如果是点击 会话标签按钮 就会对会话标签按钮BG图进行设置
    //  同时将会话列表显示出来 , 将好友列表隐藏

    //  如果是点击 好友标签按钮 就会对好友标签按钮进行设置
    //  同时 将好友列表显示出来 , 将会话列表隐藏
    tabSession.onclick = function(){
      //因为js代码执行是在html里面,所以这里的url路径是相对于html的路径
      //而css代码执行是在css里面,所以这里的url路径是相对于css的路径

        // (a.)设置图标
        tabSession.style.backgroundImage = 'url(img/会话3.png)';
        tabFriend.style.backgroundImage = 'url(img/用户1.png)';

        // (b.)显示会话列表,隐藏好友列表
        lists[0].classList = 'list';
        lists[1].classList = 'list hide';
    }

    tabFriend.onclick = function(){
      //(a.)设置图标
        tabSession.style.backgroundImage = 'url(img/会话1.png)';
        tabFriend.style.backgroundImage = 'url(img/用户3.png)';
        // (b.)显示好友列表,隐藏会话列表
        lists[0].classList = 'list hide';
        lists[1].classList = 'list';
    } 
}

//调用swicthTab方法
initSwitchTab();

//////////////////////////////////////////////
// 操作 websocket
//////////////////////////////////////////////

//创建websocket 实例
let websocket = new WebSocket("ws://127.0.0.1:8080/WebSocketMessage");

websocket.onopen = function(){
    console.log("websocket 连接成功!" );
}

websocket.onmessage = function(e){
    console.log("websocket 收到消息!"+ e.data);
    // 此时收到的 e.data  是个 json 字符串 , 需要转换成 js 对象
    let resp = JSON.parse(e.data);
    if(resp.type == "message"){
        //处理消息响应
        handleMessage(resp);//下面有对应实现的函数
    }else{
        // resp 的 type 出错!
        console.log("resp.type 不符合要求!")
    }

}

websocket.onclose = function(){
    console.log("websocket 连接关闭!");
}

websocket.onerror = function(){
    console.log("websocket 连接异常!")
}


function handleMessage(resp){
    //把 客户端 收到的消息展示出来
    // 展示到对应的会话预览区域  , 以及右侧 主消息区

    //1. 根据响应中的 sessionId 获取到当前会哈对应的 li 标签
    //      如果 li 标签不存在,则创建一个新的,如果 li 存在就调用 后面的findSessionLi函数将对应的li标签返回
    let curSessionLi = findSessionLi(resp.sessionId);
    if (curSessionLi == null){
        // 需要创建一个新的 li 标签, 表示新会话
        curSessionLi = document.createElement("li");
        curSessionLi.setAttribute("message-session-id" , resp.sessionId);
        //  此处 P 标签内部应该放消息的预览内容,一会后面统一完成这里先置为空
        curSessionLi.innerHTML = "<h3>" + resp.fromName + "</h3>"+
            "<p></p>";
        //给这个 li 标签也加上点击事件的处理
        curSessionLi.onclick = function(){
            clickSession(curSessionLi);
        }
    }
    //2. 把新的消息,显示到会话的预览区域( li 标签的 p 标签中)
    //      如果消息太长 , 就需要截断
    let p = curSessionLi.querySelector("p");
    p.innerHTML = resp.content;
    if(p.innerHTML.length > 10){
        p.innerHTML = p.innerHTML.substring(0,10)+"...";
    }
    //3. 把收到的消息的会话,放到消息列表的最上面
    let sessionListUL = document.querySelector("#session-list");
    sessionListUL.insertBefore(curSessionLi,sessionListUL.children[0]);
    //4  如果当前收到的消息的会话属于被选中状态,则把当前的消息展示到右侧的主消息列表表中
    //   新增消息的同时,注意滚动条的位置,保证新消息虽然在底部,但是能够直接被用户看到
    if (curSessionLi.className == "selected"){
        // 往消息列表添加一个新消息
        let messageShowDiv = document.querySelector(".right .message-show");
        addMessage(messageShowDiv , resp);
        scrollBottom(messageShowDiv);
    }

    //其它扩展功能: 还可以在会话窗口上给个提示 (红色的数字,显示当前有几条消息未读),还可以播放个提示音。【纯前端实现】
}

function findSessionLi(targetSessionId){
    //获取到所有会话中的 li 标签
    let sessionLis = document.querySelectorAll("#session-list li");
    for (let li of sessionLis){
        let sessionId = li.getAttribute("message-session-id");
        if(sessionId == targetSessionId){
            return li;
        }
    }
    // 触发这个操作的时机: 当前新的用户直接给新的用户直接发送当前用户的消息,此时未存在现存的 li 标签
    return null;
}

//////////////////////////////////////////////
// 实现消息发送/接收逻辑
//////////////////////////////////////////////
function initSendButton(){
    //1.获取到发送按钮 和 输入框
    let sendButton = document.querySelector(".right .ctrl button");
    let messageInput = document.querySelector(".right .message-input");
    //2.给发送按钮注册一个点击事件
    sendButton.onclick = function(){
        //(a)针对输入框内容进行判断 : 比如输入框内容为空,则啥也不干
        if(!messageInput.value){
            // value 的值是 null 或 '' 都会触发这个条件
            return;
        }

        //(b)获取当前选中的 li 标签的 sessionId
        let selectedLi  = document.querySelector("#session-list .selected");
        if(selectedLi == null){
            // 当前没有 li 标签被选中
            return;
        }

        let sessionId = selectedLi.getAttribute("message-session-id");

        //(c)构造 json 数据
        let req = {
            type: "message",
            sessionId: sessionId,
            content: messageInput.value
        };
            //细节:需要将req这个Object类型的对象转换成json格式的字符串
                //之前jquery ajax 时无需手动转,是因为 jquery 帮我们自动转换了
                //但是websocket它是原生的API不能进行自动转换
        req = JSON.stringify(req);
        console.log("[websocket send : "+ req);

        //(d)通过 websocket 发送消息
        websocket.send(req);

        //(e)发送完消息之后 , 清空之前的输入框
        messageInput.value = "";
    }
}

initSendButton();






//////////////////////////////////////////////
// 从服务器获取到用户登录的数据
//////////////////////////////////////////////

function getUserInfo(){
  $.ajax({
    type: 'get',
    url: 'userInfo',
    success: function(body){
       // 从服务器获取到数据
       // 校验结果是否有效
        if(body.userId && body.userId > 0){
       // 如果有效，则将把用户名显示到页面上
       // 同时也可以记录 userId 到html 标签的属性中.(以备后用)
       let userDiv = document.querySelector('.main .left .user');
       userDiv.innerHTML = body.username;
       userDiv.setAttribute('user-id', body.userId);

        }else{
          // 如果无效，则跳转到登录页面
          alert("当前用户未登录!");
          location.assign('login.html');

        }

    }

  });
}

getUserInfo();


//获取根据userId获取好友列表的函数调用
function getFriendList(){
    $.ajax({
        type:"get",
        url: "friendList",
        //成功回调函数-> 后端返回的结果
        success : function (body){
            //1.先清空之前创建的好友列表内容
                //通过id选择器获取之前创建的好友列表
            let friendListUL = document.querySelector('#friend-list');
            friendListUL.innerHTML = '';//将获取到的好友列表内容清空

            //2.遍历 后端返回的 body , 把服务器响应的结果 , 加回到当前 friend-list 中

            //③使用for of
            for(let friend of body){
                //friend 就是数组的每个元素
                let li = document.createElement('li');
                //设置li的内容
                li.innerHTML = "<h4>" + friend.friendName + "</h4>" ;
                //此处把 friendId 也记录下来,以备后用
                //把 friendId 作为一个 html 中的自定义属性,加到li标签中
                li.setAttribute('friend-id', friend.friendId);
                //将li添加到好友列表中
                friendListUL.appendChild(li);

                //每个 li 标签,就对应界面上的一个好友选项,给这个li加上点击事件的处理
                li.onclick = function(){
                    //参数表示区分 当前用户 点击的是哪个好友
                    clickFriend(friend);
                }

            }
        },
        error: function(){
            console.log("获取好友列表失败!");
        }
    })
}

getFriendList();


//获取会话列表
function getSessionList(){
    $.ajax({
        type:"get",
        url:"sessionList",
        success: function (body){
            //1.先清空之前创建的会话列表里面的内容->防止获取数据时罗列出重复的数据
            let sessionListUL = document.querySelector("#session-list");
            sessionListUL.innerHTML = "";
            //2.遍历响应的数组,针对数据结果构造出前端页面的样式
            for(let session of body){
                //session存储 每一条会话列表信息
                //针对 lastMessage 的长度进行截断处理
                if(session.lastMessage.length > 10){
                    session.lastMessage = session.lastMessage.substring(0, 10) + "...";
                }
                //创建一个li标签 -> 专门用来包裹每一条会话
                let li = document.createElement('li');
                //把 会话id 保存到 li 标签的自定义属性中
                li.setAttribute("message-session-id",session.sessionId);
                li.innerHTML = "<h3>" +session.friends[0].friendName + "</h3>"
                + "<p>" + session.lastMessage + "</p>";//一条会话显示用户姓名+会话信息
                sessionListUL.appendChild(li); //将li添加到会话列表中

                //给 li 标签新增点击事件
                li.onclick = function(){
                    //这个套娃的写法能保证,点击哪个 li 标签
                    //此处对应的 clickSession 函数的参数就能 拿到哪个 li标签
                    clickSession(li);
                }
            }
        }
    })
}

getSessionList();

function clickSession(currentLi){
    //1.设置高亮
    let allLis = document.querySelectorAll('#session-list>li');
    activeSession(allLis, currentLi);
    //2.获取指定会话的历史消息
    let sessionId = currentLi.getAttribute("message-session-id");

    getHistoryMessage(sessionId);


}

function activeSession(allLis, currentLi){
    //这里的循环遍历,更主要的目的是 取消未被选中的 li 标签的 className
    //遍历所有li标签
    for(let li of allLis){
        //如果当前遍历的li标签就是当前点击的li标签
        if(li === currentLi){
            //就给它添加高亮样式
            li.className = "selected";
        }else{
            //否则就移除高亮样式
            li.className = "";
        }
    }
}

// 此函数 主要获取指定会话的历史消息
function getHistoryMessage(sessionId){
    console.log("获取历史消息 sessionId = "+ sessionId);
    //1.先清空右侧列表中已有的内容
        //清空会话标题
    let titleDiv = document.querySelector(".right .title");
    titleDiv.innerHTML = "";
        //清空会话内容
    let messageShowDiv = document.querySelector(".right .message-show");
    messageShowDiv.innerHTML = "";

    //2.重新设置会话的标题. 新的会话标题是点击的那个会话上面显示的标题
    //  先找到当前选中的会话是哪个. 被选中的会话带有 selected 类的选择
    let selectedH3 = document.querySelector("#session-list .selected>h3");
    if(selectedH3){
        //selectedH3 肯呢个不存在,比如在页面价子啊阶段, 所以此时肯呢个并没有哪个会话被选中,
        // 也就没有会话 带有 sekected 标签, 此时就无法查询出 这个 selectedH3
        titleDiv.innerHTML = selectedH3.innerHTML;
    }

    //  3. 发送 ajax 请求给服务器, 获取到该会话的历史消息
    $.ajax({
        type:"get",
        url:"message?sessionId=" + sessionId,
        success: function (body){
            // 此处返回的 body 是个 js 对象数组 , 里面的每一个元素都是一条消息,
            // 直接遍历即可 获取每条消息
            for(let message of body){
                // 将每一条 message 放到存放整个消息的前端盒子messageShowDiv中
                addMessage(messageShowDiv , message);//通过下面实现具体的添加功能
            }
            //添加一个滚动条的操作:   在构造好消息列表后,控制滚动条,自动滚动到最下方
            scrollBottom(messageShowDiv);
        }
    });
 }

 //******* 消息区滚动函数scrollBottom的实现
//  把messageShowDiv里的内容滚动到最底部
function scrollBottom(elem){
    //1. 获取到可视区域的高度
    let clientHeight = elem.offsetHeight;
    //2. 获取到内容的总高度
    let scrollHeight = elem.scrollHeight;
    //3. 进行滚动操作,第一个参数是水平方向滚动的尺寸,第二个方向是垂直方向滚动的尺寸
    elem.scrollTo(0,scrollHeight - clientHeight);
}

 //************** messageSowDiv↓表示一个消息块
 function addMessage(messageShowDiv , message){
    //添加消息到右侧消息的盒子里面,我们需要分类
     // 对于自己发的消息应该靠右
     // 对于好友发的消息应该靠左

    // 使用一个 div 表示一条消息(一个消息行)
     let messageDiv = document.createElement("div");
     //selfUsername从左边登录的user名那获取
     let selfUsername = document.querySelector(".left .user").innerHTML;
     if(selfUsername == message.fromName){
         //消息是自己发的,靠右
         messageDiv.className = "message message-right";
     }else{
         //消息是别人发的,靠左
         messageDiv.className = "message message-left";
     }
     //设置消息里面的内容(一个消息快)
     messageDiv.innerHTML = "<div class='box'>"
     +"<h4>"+message.fromName+"</h4>"
     +"<p>"+message.content+"</p>"
     +"</div>";

     //将一个消息块放到一行消息里面,然后再把一行消息放到  消息区messageShowDiv 中
     messageShowDiv.appendChild(messageDiv);

 }


//点击好友列表选项,触发的函数
function clickFriend(friend){
    //1.先判定一下当前这个好友是否有对应的会话
    //  使用一个单独的函数来实现,这个函数参数是用户的名字,返回值是一个 li 标签,
        //  找到了就是返回会话列表里的li
        //  没有找到,返回 null
    let sessionLi = findSessionByName(friend.friendName);
    let sessionListUL = document.querySelector("#session-list");
    if(sessionLi){
        //2.如果存在匹配的结果,就把这个会话设置为选中状态,并且置顶
        //  insertBefore 把这个找到的 li 标签 放到最前面
        sessionListUL.insertBefore(sessionLi,sessionListUL.children[0]);
        //  此处设置会话中的选中状态,获取历史消息这两个功能在上面的clickSession中已经写过
        //  这里直接调用 clickSession即可
        //clickSession(sessionLi);
        //或者模拟一下点击操作
        sessionLi.click();
    }else{
        //3.如果不存在匹配结果,就创建一个新会话(创建 li 标签 + 通知服务器)
        sessionLi = document.createElement("li");
        // 构造li标签内容,由于新会话没有"最后一条消息", 所以 p 标签内容就设置为空即可
        sessionLi.innerHTML = "<h3>"+friend.friendName+"</h3>"+"<p></p>";
        //  把标签进行置顶
        sessionListUL.insertBefore(sessionLi,sessionListUL.children[0]);
        sessionLi.onclick =  function(){
            clickSession(sessionLi);
        }
        sessionLi.click();
        // 发消息给服务器,告诉服务器 当前创建的会话是什么样的
        createSession(friend.friendId,sessionLi);
    }
    //4.还需要将标签页切换到会话列表
    //  实现方式: 找到会话列表标签页按钮,模拟一个点击操作
    let tabSession = document.querySelector(".tab .tab-session");
    tabSession.click();
}

function findSessionByName(username){
    //先获取到会话列表中所有的li标签
    //然后依次遍历,看看这些li标签谁的名字和要查找的名字一样.
    let sessionLis = document.querySelectorAll("#session-list>li");
    for(let sessionLi of sessionLis){
        // 获取到该 li 标签里面的 h3 标签,进一步得到名字
        let h3 = sessionLi.querySelector("h3");
        if(h3.innerHTML == username){
            return sessionLi;
        }
    }
    return null;
}

// friendId 是构造 HTTP 请求时必备的信息
function createSession(friendId , sessionLi){
    $.ajax({
        type:"post",
        url:"session?toUserId=" + friendId,
        success: function(body){
            console.log("创建会话成功! sessionId = "+ body.sessionId);
            sessionLi.setAttribute("message-session-id",body.sessionId);
        },
        error: function(){
            console.log("会话创建失败.");
        }
    })

}








